<?php

namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;

class UserService
{
    /**
     * 创建用户
     *
     * @param array $data
     * @return User
     */
    public function create(array $data): User
    {
        return DB::transaction(function () use ($data) {
            $userData = [
                'username' => $data['username'],
                'nickname' => $data['nickname'] ?? null,
                'email' => $data['email'] ?? null,
                'phone' => $data['phone'] ?? null,
                'password' => Hash::make($data['password']),
                'status' => $data['status'],
                'max_devices' => $data['max_devices'] ?? 1, // 默认1台设备
                'dept_id' => $data['dept_id'] ?? null,
                'remark' => $data['remark'] ?? null,
            ];

            $user = User::create($userData);

            if (isset($data['role_ids']) && is_array($data['role_ids'])) {
                $user->roles()->sync($data['role_ids']);
            }

            return $user->load(['roles', 'department']);
        });
    }

    /**
     * 更新用户
     *
     * @param User $user
     * @param array $data
     * @return User
     */
    public function update(User $user, array $data): User
    {
        return DB::transaction(function () use ($user, $data) {
            $userData = [
                'username' => $data['username'],
                'nickname' => $data['nickname'] ?? null,
                'email' => $data['email'] ?? null,
                'phone' => $data['phone'] ?? null,
                'status' => $data['status'],
                'dept_id' => $data['dept_id'] ?? null,
                'remark' => $data['remark'] ?? null,
            ];
            
            // 如果提供了 max_devices，则更新
            if (isset($data['max_devices'])) {
                $oldMaxDevices = $user->max_devices ?? 1;
                $newMaxDevices = $data['max_devices'];
                $userData['max_devices'] = $newMaxDevices;
                
                // 如果新限制小于旧限制，且当前token数量超过新限制，删除多余的token
                if ($newMaxDevices < $oldMaxDevices) {
                    $tokenService = app(\App\Services\TokenService::class);
                    $tokenCount = $tokenService->getTokenCount($user->id);
                    
                    // 记录被踢出的设备数量
                    $kickedOutCount = 0;
                    
                    // 删除多余的token（从最旧的开始删除）
                    while ($tokenCount >= $newMaxDevices) {
                        $kickedOutDevice = $tokenService->removeOldestToken($user->id);
                        if ($kickedOutDevice) {
                            $kickedOutCount++;
                            
                            // 删除对应的在线用户记录
                            if (isset($kickedOutDevice['token'])) {
                                $onlineUser = \App\Models\OnlineUser::where('token', $kickedOutDevice['token'])->first();
                                if ($onlineUser) {
                                    // 记录设备被踢出的日志
                                    try {
                                        \App\Models\LoginLog::create([
                                            'user_id' => $user->id,
                                            'username' => $user->username,
                                            'ip' => $onlineUser->ip,
                                            'user_agent' => $onlineUser->user_agent,
                                            'status' => 'kicked_out',
                                            'message' => '设备被踢出：管理员将设备上限从 ' . $oldMaxDevices . ' 调整为 ' . $newMaxDevices,
                                            'login_at' => now(),
                                        ]);
                                    } catch (\Exception $logEx) {
                                        \Log::warning('记录设备被踢出日志失败: ' . $logEx->getMessage());
                                    }
                                    
                                    $onlineUser->delete();
                                }
                            }
                        }
                        $tokenCount--;
                    }
                    
                    // 记录操作日志
                    if ($kickedOutCount > 0) {
                        try {
                            \App\Models\OperationLog::create([
                                'user_id' => auth()->id(),
                                'username' => auth()->user()->username ?? 'system',
                                'method' => 'PUT',
                                'action' => 'update',
                                'resource' => 'users',
                                'resource_id' => $user->id,
                                'description' => "更新用户设备限制：从 {$oldMaxDevices} 调整为 {$newMaxDevices}，已踢出 {$kickedOutCount} 台设备",
                                'path' => request()->path(),
                                'params' => request()->all(),
                                'ip' => request()->ip(),
                                'user_agent' => request()->userAgent(),
                                'status' => 'success',
                            ]);
                        } catch (\Exception $opLogEx) {
                            \Log::warning('记录设备限制更新操作日志失败: ' . $opLogEx->getMessage());
                        }
                    }
                }
            }

            // 检查是否更新了密码
            $passwordChanged = false;
            if (isset($data['password']) && !empty($data['password'])) {
                $userData['password'] = Hash::make($data['password']);
                $passwordChanged = true;
            }

            // 检查是否更新了用户名
            $usernameChanged = false;
            if (isset($data['username']) && $data['username'] !== $user->username) {
                $usernameChanged = true;
            }

            $user->update($userData);

            // 如果更新了密码或用户名，删除所有token（强制重新登录）
            if ($passwordChanged || $usernameChanged) {
                $tokenService = app(\App\Services\TokenService::class);
                try {
                    // 获取所有token以便删除对应的在线用户记录
                    $oldTokens = $tokenService->getUserTokens($user->id);
                    $tokenService->removeAll($user->id);
                    
                    // 删除对应的在线用户记录
                    if (!empty($oldTokens)) {
                        $oldTokenValues = array_column($oldTokens, 'token');
                        \App\Models\OnlineUser::whereIn('token', $oldTokenValues)->delete();
                    } else {
                        // 如果没有token信息，删除该用户的所有在线记录
                        \App\Models\OnlineUser::where('user_id', $user->id)->delete();
                    }
                } catch (\Exception $e) {
                    \Log::warning('删除用户Token失败: ' . $e->getMessage(), [
                        'user_id' => $user->id,
                        'reason' => $passwordChanged ? 'password_changed' : 'username_changed'
                    ]);
                }
            }

            if (isset($data['role_ids']) && is_array($data['role_ids'])) {
                $user->roles()->sync($data['role_ids']);
            }

            return $user->load(['roles', 'department']);
        });
    }

    /**
     * 删除用户
     *
     * @param User $user
     * @return bool
     */
    public function delete(User $user): bool
    {
        return DB::transaction(function () use ($user) {
            $user->roles()->detach();
            return $user->delete();
        });
    }

    /**
     * 构建查询
     *
     * @param array $filters
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function buildQuery(array $filters = [])
    {
        $query = User::with(['roles', 'department']);

        if (isset($filters['username'])) {
            // 转义LIKE查询中的特殊字符，防止注入攻击
            $username = str_replace(['%', '_'], ['\%', '\_'], $filters['username']);
            $query->where('username', 'like', '%' . $username . '%');
        }

        if (isset($filters['status'])) {
            // 确保status是整数
            $query->where('status', (int)$filters['status']);
        }

        if (isset($filters['dept_id'])) {
            // 确保dept_id是整数
            $query->where('dept_id', (int)$filters['dept_id']);
        }

        return $query->orderBy('id', 'desc');
    }
}

